home *** CD-ROM | disk | FTP | other *** search
- //***************************************************************************
- //
- // this file is (c) '94-'96 Niklas Beisert
- //
- // this file is part of the cubic player development kit.
- // you may only use/modify/spread this file under the terms stated
- // in the cubic player development kit accompanying documentation.
- //
- //***************************************************************************
-
-
- //[filetype 10]
- // color=3
- // name=XM
- // interface=_plCubicPlayer
- // player=_gmdPlayer
- // ldlink=loadxm
- // loader=mpLoadXM_
-
-
- // loader example
-
- #include <string.h>
- #include "binfile.h"
-
- #include "mcp.h"
- #include "mp.h"
- #include "err.h"
-
- static inline void putcmd(unsigned char *&p, unsigned char c, unsigned char d)
- {
- *p++=c;
- *p++=d;
- }
-
- static inline void advancenote(unsigned char *&x)
- {
- unsigned char s=*x;
- if (s&0x80)
- {
- x++;
- if (s&1)
- x++;
- if (s&2)
- x++;
- if (s&4)
- x++;
- if (s&8)
- x++;
- if (s&16)
- x++;
- }
- else
- x+=5;
- }
-
- extern "C" int mpLoadXM(module &m, binfile &file)
- {
- m.reset();
-
- struct
- {
- char sig[17];
- char name[20];
- char whythis1a;
- char tracker[20];
- unsigned short ver;
- unsigned long hdrsize;
- } head1;
-
- struct
- {
- unsigned short ordnum;
- unsigned short restart;
- unsigned short channum;
- unsigned short patnum;
- unsigned short insnum;
- unsigned short freqtab;
- unsigned short tempo;
- unsigned short speed;
- unsigned char ord[256];
- } head2;
-
- file.read(&head1, sizeof(head1));
- if (memcmp(head1.sig, "Extended Module: ", 17))
- return errFormSig;
- if (head1.whythis1a!=26)
- return errFormStruc;
- if (head1.ver<0x104)
- return errFormOldVer;
- file.read(&head2, sizeof(head2));
- file.seekcur(head1.hdrsize-4-sizeof(head2));
-
- if (!head2.insnum)
- return errFormMiss;
-
- memcpy(m.name, head1.name, 20);
- m.name[20]=0;
-
- m.options=(head2.freqtab&1)?MOD_EXPOFREQ:0;
- m.channum=head2.channum;
- m.instnum=head2.insnum;
- m.envnum=head2.insnum*2;
- m.patnum=head2.patnum+1;
- m.ordnum=head2.ordnum;
- m.endord=m.ordnum;
- m.tracknum=(head2.channum+1)*head2.patnum+1;
- m.loopord=head2.restart;
-
- sampleinfo **smps=new sampleinfo *[m.instnum];
- sample **msmps=new sample *[m.instnum];
- int *instsmpnum=new int [m.instnum];
- if (!instsmpnum||!m.allocinstruments()||!m.allocpatterns()||!m.alloctracks()||!m.allocenvelopes()||!smps||!msmps||!m.allocorders())
- return errAllocMem;
-
- int i,t,j;
-
- for (i=0; i<m.ordnum; i++)
- m.orders[i]=(head2.ord[i]<head2.patnum)?head2.ord[i]:head2.patnum;
-
- for (i=0; i<m.channum; i++)
- m.patterns[head2.patnum].tracks[i]=m.tracknum-1;
- m.patterns[head2.patnum].gtrack=m.tracknum-1;
- m.patterns[head2.patnum].patlen=64;
-
- unsigned char *temptrack=new unsigned char[3000];
- unsigned short buflen=2048;
- unsigned char *buffer=new unsigned char[buflen];
- if (!buffer||!temptrack)
- return errAllocMem;
-
- for (t=0; t<head2.patnum; t++)
- {
- struct
- {
- unsigned long len;
- unsigned char ptype;
- unsigned short rows;
- unsigned short patdata;
- } pathead;
- file.read(&pathead, sizeof(pathead));
- file.seekcur(pathead.len-sizeof(pathead));
-
- pattern &pp=m.patterns[t];
- for (i=0; i<m.channum; i++)
- pp.tracks[i]=t*(m.channum+1)+i;
- pp.gtrack=t*(m.channum+1)+m.channum;
- pp.patlen=pathead.rows;
-
- int clean=0;
- if (pathead.patdata==0)
- {
- clean=1;
- pathead.patdata=m.channum*pathead.rows;
- }
-
- if (pathead.patdata>buflen)
- {
- buflen=pathead.patdata;
- delete buffer;
- buffer=new unsigned char[buflen];
- if (!buffer)
- return errAllocMem;
- }
- if (clean)
- memset(buffer, 0x80, pathead.patdata);
- else
- file.read(buffer, pathead.patdata);
-
- for (i=0; i<m.channum; i++)
- {
- unsigned char *tp=temptrack;
- unsigned char *buf=buffer;
-
- char xxq;
- for (xxq=0; xxq<i; xxq++)
- advancenote(buf);
-
- unsigned short row;
- for (row=0; row<pathead.rows; row++)
- {
- unsigned char *cp=tp+2;
-
- signed short nte=-1;
- unsigned char vol=0;
- signed short pan=-1;
- signed short volv=-1;
- signed short ins=-1;
- unsigned char command=0;
- unsigned char data=0;
-
- unsigned char x=0x1F;
- if (*buf&0x80)
- x=*buf++&~0x80;
- if (x&1)
- {
- nte=11+(*buf++&~0x80);
- if (nte==11) // ???
- nte=-1;
- }
- if (x&2)
- ins=*buf++-1;
- if (x&4)
- vol=*buf++;
- if (x&8)
- command=*buf++;
- if (x&16)
- data=*buf++;
- if (row!=(pathead.rows-1))
- for (xxq=0; xxq<(m.channum-1); xxq++)
- advancenote(buf);
-
- if ((vol>=0x10)&&(vol<=0x50))
- volv=vol-0x10;
-
- if (command==0xC)
- volv=data;
-
- if ((vol&0xF0)==0xC0)
- pan=(vol&0xF)+((vol&0xF)<<4);
-
- if (command==0x8)
- pan=data;
-
- if ((command==0xE)&&((data&0xF0)==0x80))
- pan=(data&0xF)+((data&0xF)<<4);
-
- if (((command==0x3)||(command==0x5)||((vol&0xF0)==0xF0))&&(nte!=-1)&&(nte!=108))
- nte|=128;
-
- if ((ins!=-1)||(nte!=-1)||(volv!=-1)||(pan!=-1))
- {
- if (nte==108)
- {
- putcmd(cp, cmdKeyOff, 0);
- nte=-1;
- }
- unsigned char &act=*cp;
- *cp++=cmdPlayNote;
- if (ins!=-1)
- {
- act|=cmdPlayIns;
- *cp++=ins;
- }
- if (nte!=-1)
- {
- act|=cmdPlayNte;
- *cp++=nte;
- }
- if (volv!=-1)
- {
- act|=cmdPlayVol;
- *cp++=(volv==0x40)?0xFF:(volv<<2);
- }
- if (pan!=-1)
- {
- act|=cmdPlayPan;
- *cp++=pan;
- }
- if ((command==0xE)&&((data>>4)==0xD))
- {
- act|=cmdPlayDelay;
- *cp++=data&0xF;
- }
- }
-
- if ((vol&0xF0)==0x60)
- if (vol&0xF)
- putcmd(cp, cmdVolSlideDown, (vol&0x0F)<<2);
-
- if ((vol&0xF0)==0x70)
- if (vol&0xF)
- putcmd(cp, cmdVolSlideUp, (vol&0x0F)<<2);
-
- if ((vol&0xF0)==0x80)
- if (vol&0xF)
- putcmd(cp, cmdRowVolSlideDown, (vol&0x0F)<<2);
-
- if ((vol&0xF0)==0x90)
- if (vol&0xF)
- putcmd(cp, cmdRowVolSlideUp, (vol&0x0F)<<2);
-
- if ((vol&0xF0)==0xA0)
- putcmd(cp, cmdPitchVibratoSetSpeed, vol&0x0F);
-
- if ((vol&0xF0)==0xB0)
- putcmd(cp, cmdPitchVibrato, (vol&0x0F)<<4);
-
- if ((vol&0xF0)==0xD0)
- if (vol&0xF)
- putcmd(cp, cmdPanSlide, -(vol&0x0F));
-
- if ((vol&0xF0)==0xE0)
- if (vol&0xF)
- putcmd(cp, cmdPanSlide, vol&0x0F);
-
- if ((vol&0xFFF0)==0xF0)
- putcmd(cp, cmdPitchSlideToNote, (vol&0x0F)<<4);
-
- switch (command)
- {
- case 0x0:
- if (data)
- putcmd(cp, cmdArpeggio, data);
- break;
- case 0x1:
- putcmd(cp, cmdPitchSlideUp, data);
- break;
- case 0x2:
- putcmd(cp, cmdPitchSlideDown, data);
- break;
- case 0x3:
- putcmd(cp, cmdPitchSlideToNote, data);
- break;
- case 0x4:
- putcmd(cp, cmdPitchVibrato, data);
- break;
- case 0x5:
- putcmd(cp, cmdPitchSlideToNote, 0);
- if (!data)
- putcmd(cp, cmdSpecial, cmdContVolSlide);
- else
- if (data&0xF0)
- putcmd(cp, cmdVolSlideUp, (data>>4)<<2);
- else
- putcmd(cp, cmdVolSlideDown, (data&0xF)<<2);
- break;
- case 0x6:
- putcmd(cp, cmdPitchVibrato, 0);
- if (!data)
- putcmd(cp, cmdSpecial, cmdContVolSlide);
- else
- if (data&0xF0)
- putcmd(cp, cmdVolSlideUp, (data>>4)<<2);
- else
- putcmd(cp, cmdVolSlideDown, (data&0xF)<<2);
- break;
- case 0x7:
- putcmd(cp, cmdVolVibrato, data);
- break;
- case 0x9:
- if (nte!=-1)
- putcmd(cp, cmdOffset, data);
- break;
- case 0xA:
- if (!data)
- putcmd(cp, cmdSpecial, cmdContVolSlide);
- else
- if (data&0xF0)
- putcmd(cp, cmdVolSlideUp, (data>>4)<<2);
- else
- putcmd(cp, cmdVolSlideDown, (data&0xF)<<2);
- break;
- case 0xE:
- command=data>>4;
- data&=0xF;
- switch (command)
- {
- case 0x1:
- putcmd(cp, cmdRowPitchSlideUp, data<<4);
- break;
- case 0x2:
- putcmd(cp, cmdRowPitchSlideDown, data<<4);
- break;
- case 0x3:
- putcmd(cp, cmdSpecial, data?cmdGlissOn:cmdGlissOff);
- break;
- case 0x4:
- if (data<4)
- putcmd(cp, cmdPitchVibratoSetWave, data);
- break;
- case 0x7:
- if (data<4)
- putcmd(cp, cmdVolVibratoSetWave, data);
- break;
- case 0x9:
- if (data)
- putcmd(cp, cmdRetrig, data);
- break;
- case 0xA:
- putcmd(cp, cmdRowVolSlideUp, data<<2);
- break;
- case 0xB:
- putcmd(cp, cmdRowVolSlideDown, data<<2);
- break;
- case 0xC:
- putcmd(cp, cmdNoteCut, data);
- break;
- }
- break;
- case 0x14:
- putcmd(cp, cmdKeyOff, 0);
- break;
- case 0x15:
- if (data)
- putcmd(cp, cmdSetEnvPos, data);
- break;
- case 0x19:
- if (!data)
- putcmd(cp, cmdPanSlide, 0);
- else
- if (data&0xF0)
- putcmd(cp, cmdPanSlide, data>>4);
- else
- putcmd(cp, cmdPanSlide, -(data&0xF));
- break;
- case 0x1B:
- putcmd(cp, cmdRetrig, data);
- break;
- case 0x1D:
- putcmd(cp, cmdTremor, data);
- break;
- case 0x21:
- if ((data&0xF0)==0x10)
- putcmd(cp, cmdRowPitchSlideUp, (data&0xF)<<2);
- else
- if ((data&0xF0)==0x20)
- putcmd(cp, cmdRowPitchSlideDown, (data&0xF)<<2);
- break;
- case 0x22:
- putcmd(cp, cmdPanHeight, (data>>4)*0x11);
- putcmd(cp, cmdPanDepth, (data&0xF)*0x11);
- break;
- }
-
- if (cp!=(tp+2))
- {
- tp[0]=row;
- tp[1]=cp-tp-2;
- tp=cp;
- }
- }
-
- track &trk=m.tracks[t*(m.channum+1)+i];
- unsigned short len=tp-temptrack;
-
- if (!len)
- trk.ptr=trk.end=0;
- else
- {
- trk.ptr=new unsigned char[len];
- trk.end=trk.ptr+len;
- if (!trk.ptr)
- return errAllocMem;
- memcpy(trk.ptr, temptrack, len);
- }
- }
-
- unsigned char *tp=temptrack;
- unsigned char *buf=buffer;
-
- unsigned short row, q;
- for (row=0; row<pathead.rows; row++)
- {
- unsigned char *cp=tp+2;
- if (!row&&(t==head2.ord[0]))
- {
- if (head2.tempo!=6)
- putcmd(cp, cmdTempo, head2.tempo);
- if (head2.speed!=125)
- putcmd(cp, cmdSpeed, head2.speed);
- }
- for (q=0; q<m.channum; q++)
- {
- unsigned char x=0x1F;
- if (*buf&0x80)
- x=*buf++&~0x80;
-
- signed short command=-1;
- unsigned char data=0;
-
- if (x&1)
- buf++;
- if (x&2)
- buf++;
- if (x&4)
- buf++;
- if (x&8)
- command=*buf++;
- if (x&16)
- data=*buf++;
-
- switch (command)
- {
- case 0xB:
- putcmd(cp, cmdGoto, data);
- break;
- case 0xD:
- putcmd(cp, cmdBreak, (data&0x0F)+(data>>4)*10);
- break;
- case 0xE:
- switch (data>>4)
- {
- case 0x6:
- putcmd(cp, cmdSetChan, q);
- putcmd(cp, cmdPatLoop, data&0xF);
- break;
- case 0xE:
- putcmd(cp, cmdPatDelay, data&0xF);
- break;
- }
- break;
- case 0xF:
- if (data)
- if (data<0x20)
- putcmd(cp, cmdTempo, data);
- else
- putcmd(cp, cmdSpeed, data);
- else
- putcmd(cp, cmdGoto, 0);
- break;
- case 0x10:
- putcmd(cp, cmdGlobVol, (data>0x3F)?0xFF:(data<<2));
- break;
- case 0x11:
- if ((data&0x0F)&&(data&0xF0))
- break;
- putcmd(cp, cmdSetChan, q);
- if (data&0xF0)
- putcmd(cp, cmdGlobVolSlide, (data>>4)<<2);
- else
- putcmd(cp, cmdGlobVolSlide, -((data&0xF)<<2));
- }
- }
- if (cp!=(tp+2))
- {
- tp[0]=row;
- tp[1]=cp-tp-2;
- tp=cp;
- }
- }
-
- track &trk=m.tracks[t*(m.channum+1)+m.channum];
- unsigned short len=tp-temptrack;
-
- if (!len)
- trk.ptr=trk.end=0;
- else
- {
- trk.ptr=new unsigned char[len];
- trk.end=trk.ptr+len;
- if (!trk.ptr)
- return errAllocMem;
- memcpy(trk.ptr, temptrack, len);
- }
- }
-
- delete temptrack;
- delete buffer;
-
- m.sampnum=0;
- m.modsampnum=0;
- for (i=0; i<m.instnum; i++)
- {
- instrument &ip=m.instruments[i];
- envelope *env=m.envelopes+2*i;
- smps[i]=0;
- msmps[i]=0;
- struct
- {
- unsigned long size;
- char name[22];
- char type;
- unsigned short samp;
- } ins1;
- file.read(&ins1, sizeof(ins1));
- memcpy(ip.name, ins1.name, 22);
- ip.name[22]=0;
- instsmpnum[i]=ins1.samp;
- if (!ins1.samp)
- {
- file.seekcur(ins1.size-sizeof(ins1));
- continue;
- }
- struct
- {
- unsigned long shsize;
- unsigned char snum[96];
- unsigned short venv[12][2];
- unsigned short penv[12][2];
- unsigned char vnum, pnum;
- unsigned char vsustain, vloops, vloope, psustain, ploops, ploope;
- unsigned char vtype, ptype;
- unsigned char vibtype, vibsweep, vibdepth, vibrate;
- unsigned short volfade;
- unsigned short res;
- } ins2;
- file.read(&ins2, sizeof(ins2));
- file.seekcur(ins1.size-sizeof(ins1)-sizeof(ins2));
-
- smps[i]=new sampleinfo[ins1.samp];
- msmps[i]=new sample[ins1.samp];
- if (!ip.samples||!smps[i]||!msmps[i])
- return errAllocMem;
- memset(msmps[i], 0, sizeof(**msmps)*ins1.samp);
- memset(smps[i], 0, sizeof(**smps)*ins1.samp);
-
- for (j=0; j<96; j++)
- if (ins2.snum[j]<ins1.samp)
- ip.samples[j+12]=m.modsampnum+ins2.snum[j];
- unsigned short volfade=0xFFFF;
- if (ins2.vtype&1)
- {
- volfade=ins2.volfade;
- env[0].speed=0;
- env[0].type=0;
- env[0].env=new unsigned char[ins2.venv[ins2.vnum-1][0]+1];
- if (!env[0].env)
- return errAllocMem;
- short k, p=0, h=ins2.venv[0][1]*4;
- for (j=1; j<ins2.vnum; j++)
- {
- short l=ins2.venv[j][0]-p;
- short dh=ins2.venv[j][1]*4-h;
- for (k=0; k<l; k++)
- {
- short cv=h+dh*k/l;
- env[0].env[p++]=(cv>255)?255:cv;
- }
- h+=dh;
- }
- env[0].len=p;
- env[0].env[p]=(h>255)?255:h;
- if (ins2.vtype&2)
- {
- env[0].type|=mpEnvSLoop;
- if (!(ins2.vtype&4)||(ins2.vsustain<=ins2.vloope))
- {
- env[0].sloops=ins2.venv[ins2.vsustain][0];
- env[0].sloope=ins2.venv[ins2.vsustain][0]+1;
- }
- else
- {
- env[0].sloops=ins2.venv[ins2.vloops][0];
- env[0].sloope=ins2.venv[ins2.vloope][0];
- }
- }
- if (ins2.vtype&4)
- {
- if ((ins2.vtype&2)&&(ins2.vsustain==ins2.vloope))
- {
- env[0].type|=mpEnvSLoop;
- env[0].sloops=ins2.venv[ins2.vloops][0];
- env[0].sloope=ins2.venv[ins2.vloope][0];
- }
- else
- {
- env[0].type|=mpEnvLoop;
- env[0].loops=ins2.venv[ins2.vloops][0];
- env[0].loope=ins2.venv[ins2.vloope][0];
- }
- }
- }
- if (ins2.ptype&1)
- {
- env[1].speed=0;
- env[1].type=0;
- env[1].env=new unsigned char[ins2.penv[ins2.pnum-1][0]+1];
- if (!env[1].env)
- return errAllocMem;
- short k, p=0, h=ins2.penv[0][1]*4;
- for (j=1; j<ins2.pnum; j++)
- {
- short l=ins2.penv[j][0]-p;
- short dh=ins2.penv[j][1]*4-h;
- for (k=0; k<l; k++)
- {
- short cv=h+dh*k/l;
- env[1].env[p++]=(cv>255)?255:cv;
- }
- h+=dh;
- }
- env[1].len=p;
- env[1].env[p]=(h>255)?255:h;
- if (ins2.ptype&2)
- {
- env[1].type|=mpEnvSLoop;
- if (!(ins2.ptype&4)||(ins2.psustain<=ins2.ploope))
- {
- env[1].sloops=ins2.penv[ins2.psustain][0];
- env[1].sloope=ins2.penv[ins2.psustain][0]+1;
- }
- else
- {
- env[1].sloops=ins2.penv[ins2.ploops][0];
- env[1].sloope=ins2.penv[ins2.ploope][0];
- }
- }
- if (ins2.ptype&4)
- {
- if ((ins2.ptype&2)&&(ins2.psustain==ins2.ploope))
- {
- env[1].type|=mpEnvSLoop;
- env[1].sloops=ins2.penv[ins2.ploops][0];
- env[1].sloope=ins2.penv[ins2.ploope][0];
- }
- else
- {
- env[1].type|=mpEnvLoop;
- env[1].loops=ins2.penv[ins2.ploops][0];
- env[1].loope=ins2.penv[ins2.ploope][0];
- }
- }
- }
- /*
- unsigned char pchsweep;
- if (ins2.vibdepth&&ins2.vibrate)
- {
- env[2].speed=0;
- env[2].opt=0;
- env[2].len=256;
- env[2].sustain=-1;
- env[2].loops=0;
- env[2].loope=256;
- env[2].env=new unsigned char [256];
- if (!env[2].env)
- return errAllocMem;
- unsigned char ph=0;
- for (j=0; j<256; j++)
- {
- ph+=ins2.vibrate;
- switch (ins2.vibtype)
- {
- case 0:
- env[2].env[j]=128+((ins2.vibdepth*vibsintab[ph])>>10);
- break;
- case 1:
- env[2].env[j]=128+((ins2.vibdepth*(64-(ph&128)))>>5);
- break;
- case 2:
- env[2].env[j]=128+((ins2.vibdepth*(128-ph))>>6);
- break;
- case 3:
- env[2].env[j]=128+((ins2.vibdepth*(ph-128))>>6);
- break;
- }
- }
- }
- */
- for (j=0; j<ins1.samp; j++)
- {
- struct
- {
- unsigned long samplen;
- unsigned long loopstart;
- unsigned long looplen;
- unsigned char vol;
- signed char finetune;
- unsigned char type;
- unsigned char pan;
- signed char relnote;
- unsigned char res;
- unsigned char name[22];
- } samp;
- file.read(&samp, sizeof (samp));
- file.seekcur(ins2.shsize-sizeof(samp));
- if (samp.type&16)
- {
- samp.samplen>>=1;
- samp.loopstart>>=1;
- samp.looplen>>=1;
- }
-
- sample &sp=msmps[i][j];
- memcpy(sp.name, samp.name, 22);
- sp.name[22]=0;
- sp.handle=0xFFFF;
- sp.normnote=-samp.relnote*256-samp.finetune*2;
- sp.stdvol=(samp.vol>0x3F)?0xFF:(samp.vol<<2);
- sp.stdpan=samp.pan;
- sp.opt=0;
- sp.volfade=volfade;
- sp.vibtype=ins2.vibtype;
- sp.vibdepth=ins2.vibdepth<<2;
- sp.vibspeed=0;
- sp.vibrate=ins2.vibrate<<8;
- sp.vibsweep=0xFFFF/(ins2.vibsweep+1);
- sp.volenv=env[0].env?(2*i+0):0xFFFF;
- sp.panenv=env[1].env?(2*i+1):0xFFFF;
- sp.pchenv=0xFFFF;
-
- sampleinfo &sip=smps[i][j];
- sip.length=samp.samplen;
- sip.loopstart=samp.loopstart;
- sip.loopend=samp.loopstart+samp.looplen;
- sip.samprate=8363;
- sip.type=mcpSampDelta|((samp.type&16)?mcpSamp16Bit:0)|((samp.type&3)?(((samp.type&3)==2)?(mcpSampLoop|mcpSampBiDi):mcpSampLoop):0);
- }
- for (j=0; j<ins1.samp; j++)
- {
- sample &sp=msmps[i][j];
- sampleinfo &sip=smps[i][j];
- unsigned long l=sip.length<<(!!(sip.type&mcpSamp16Bit));
- if (!l)
- continue;
- sip.ptr=new char [l+16];
- if (!sip.ptr)
- return errAllocMem;
- file.read(sip.ptr, l);
- sp.handle=m.sampnum+j;
- }
- m.sampnum+=ins1.samp;
- m.modsampnum+=ins1.samp;
- }
-
- if (!m.allocsamples()||!m.allocmodsamples())
- return errAllocMem;
-
- m.sampnum=0;
- m.modsampnum=0;
- for (i=0; i<m.instnum; i++)
- {
- for (j=0; j<instsmpnum[i]; j++)
- {
- m.samples[m.sampnum++]=smps[i][j];
- m.modsamples[m.modsampnum++]=msmps[i][j];
- }
- delete smps[i];
- delete msmps[i];
- }
- delete smps;
- delete msmps;
- delete instsmpnum;
-
- return errOk;
- }
-